home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 398 / 398.xpi / chrome / forecastfox.jar / content / forecastfox.js < prev    next >
Text File  |  2010-02-04  |  33KB  |  988 lines

  1. /*------------------------------------------------------------------------------
  2.   Copyright (c) 2008 Ensolis, LLC. All Rights Reserved.
  3.   ----------------------------------------------------------------------------*/
  4.  
  5. // constants
  6. const FF_TIME_NIGHT = -1; // time that night switches to day
  7. const FF_TIME_DAY = 15;  // time that day switches to night
  8. const FF_TIMER = 90*1000; // one minute 30 second timer
  9. const ffIErrorItem = Components.interfaces.ffIErrorItem;
  10.  
  11. //global forecastfox object
  12. var gForecastfox = null;
  13.  
  14. function ffLoad()
  15. {
  16.   gForecastfox = new Forecastfox();
  17.   gForecastfox.start();
  18. }
  19.  
  20. function ffUnload()
  21. {
  22.   gForecastfox.stop();
  23.   gForecastfox = null;
  24. }
  25.  
  26. ///////////////////////
  27. // Forecastfox Object
  28. function Forecastfox() {}
  29. Forecastfox.prototype = {
  30.   _manager: null,
  31.   _bundle: null,
  32.   _prefixes: null,
  33.   _timer: null,
  34.   
  35.   start: function Forecastfox_start()
  36.   {
  37.     //get our XPCOM manager service
  38.     var obs = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
  39.     this._manager = Components.classes["@ensolis.com/forecastfox/manager-service;1"].getService(Components.interfaces.ffIManagerService);
  40.     this._bundle = document.getElementById("ff-bundle");  
  41.                   
  42.     //setup object
  43.     this._prefixes = {};
  44.     this._prefixes["cc"] = "current";
  45.     this._prefixes["dayf"] = "forecast";
  46.     this._prefixes["dayt"] = "forecast";
  47.  
  48.     //add observer to forecastfox:update
  49.     obs.addObserver(this, "forecastfox-manager", false);
  50.     
  51.     //setup display - give window a chance to display before loading
  52.     var comp = this;
  53.     if (!this._manager.isRunning)
  54.       window.setTimeout(function() { comp._manager.run(false); }, 500);
  55.     else
  56.       window.setTimeout(function() { comp._update("display"); }, 500);
  57.   },
  58.  
  59.   stop: function Forecastfox_stop()
  60.   {
  61.     try {
  62.       //remove observers
  63.       var obs = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
  64.       obs.removeObserver(this, "forecastfox-manager");
  65.       obs = null;
  66.     } catch(e) {}
  67.  
  68.     // clear progress timer
  69.     if (this._timer) {
  70.       window.clearTimeout(this._timer);
  71.       this._timer = null;
  72.     }
  73.     
  74.     //destroy variables
  75.     this._manager = null;
  76.     this._bundle = null;
  77.     this._prefixes = null;
  78.   },
  79.   
  80.   observe: function Forecastfox_observe(aSubject, aTopic, aData)
  81.   {
  82.     var comp = this;
  83.     window.setTimeout(function() { comp._update(aData); }, 0);
  84.   },
  85.   
  86.   hideContext: function Forecastfox_hideContext()
  87.   {
  88.     var node = document.getElementById("ff-popup");    
  89.     node.hidePopup();
  90.   },
  91.   
  92.   addIcons: function Forecastfox_addIcons(aEvent)
  93.   {
  94.     var icnSvc = this._manager.icons;    
  95.     var node = aEvent.target;
  96.  
  97.     //remove old elements
  98.     while (node.hasChildNodes() && node.lastChild.tagName != "menuseparator")
  99.         node.removeChild(node.lastChild);
  100.     
  101.     //get icons
  102.     var items = icnSvc.getItems({});
  103.     var id = icnSvc.current.ID;
  104.         
  105.     //set none
  106.     var item;    
  107.     if (items.length == 0) {
  108.       item = document.createElement("menuitem");
  109.       item.setAttribute("label", this._bundle.getString("ff.icons.none"));
  110.       item.setAttribute("disabled", true);
  111.       node.appendChild(item);
  112.       return;
  113.     }
  114.     
  115.     //set for one or more
  116.     for (var i=0; i<items.length; i++) {
  117.       item = document.createElement("menuitem");
  118.       item.setAttribute("label", items[i].name);
  119.       item.setAttribute("value", items[i].ID);
  120.       item.setAttribute("type", "radio");
  121.       item.setAttribute("name", "icon");     
  122.       if (items[i].ID == id)
  123.         item.setAttribute("checked", "true");
  124.       node.appendChild(item);
  125.     }    
  126.   },
  127.     
  128.   selectIcon: function Forecastfox_selectIcon(aEvent)
  129.   {
  130.     var icnSvc = this._manager.icons;
  131.       
  132.     //set if not current
  133.     var node = aEvent.target;
  134.     var id = node.getAttribute("value");
  135.     if (id != icnSvc.current.ID && id != "ff-icons-more")
  136.       icnSvc.current = icnSvc.getItem(id);
  137.  
  138.     node.parentNode.hidePopup();
  139.   },
  140.     
  141.   addProfiles: function Forecastfox_addProfiles(aEvent)
  142.   {
  143.     var prfSvc = this._manager.profiles;    
  144.     var node = aEvent.target;
  145.  
  146.     //remove old elements
  147.     while (node.hasChildNodes() && node.lastChild.tagName != "menuseparator")
  148.         node.removeChild(node.lastChild);
  149.         
  150.     //get profiles
  151.     var items = prfSvc.getItems({});
  152.     var id = prfSvc.current.ID;
  153.         
  154.     //set none
  155.     var item;    
  156.     if (items.length == 0) {
  157.       item = document.createElement("menuitem");
  158.       item.setAttribute("label", this._bundle.getString("ff.profiles.none"));
  159.       item.setAttribute("disabled", true);
  160.       node.appendChild(item);
  161.       return;
  162.     }  
  163.     
  164.     //set for one or more
  165.     for (var i=0; i<items.length; i++) {
  166.       item = document.createElement("menuitem");
  167.       item.setAttribute("label", items[i].name);
  168.       item.setAttribute("type", "radio");
  169.       item.setAttribute("name", "profile");
  170.       item.setAttribute("value", items[i].ID);     
  171.       if (items[i].ID == id)
  172.         item.setAttribute("checked", "true");
  173.       node.appendChild(item);
  174.     }     
  175.   },
  176.   
  177.   selectProfile: function Forecastfox_selectProfile(aEvent)
  178.   {
  179.     var prfSvc = this._manager.profiles;
  180.      
  181.     //set if not current
  182.     var node = aEvent.target;
  183.     var id = node.getAttribute("value");
  184.     if (id != prfSvc.current.ID)
  185.       prfSvc.current = prfSvc.getItem(id);
  186.  
  187.     node.parentNode.hidePopup();
  188.   },
  189.  
  190.   clickLink: function Forecastfox_clickLink(aEl, event)
  191.   {
  192.     //middle clicked  
  193.     if (event.button == 1) {
  194.     
  195.       //do oncommand
  196.       eval(aEl.getAttribute("oncommand"));    
  197.     }
  198.   },
  199.    
  200.   openLink: function Forecastfox_openLink(aEvent, aUnits, aPartner, aFrom)
  201.   {
  202.     // supply an aOpenEvent and it will be used in the openUILink instead of the aEvent
  203.     var url = aEvent.target.getAttribute("url");
  204.     if (url == "") {
  205.       url = this._bundle.getString("ff.url.default");
  206.       aPartner = true;
  207.       aUnits = false;
  208.     }
  209.     
  210.     var separator = (url.indexOf("?") != -1) ? "&" : "?";
  211.     if (aPartner)
  212.       url += separator + "partner=" + this._manager.partner;
  213.     if (aUnits) {
  214.       separator = (url.indexOf("?") != -1) ? "&" : "?";
  215.          url += separator + "metric=" + this._manager.getPref("units.current");
  216.     }
  217.  
  218.     this._manager.openLink(url, this._getWhere(aEvent, aFrom));
  219.   },
  220.   
  221.   importDOM: function Forecastfox_importDOM()
  222.   {
  223.     var success = this._manager.migrator.importDOM(window);
  224.     var prompter = this._getPrompter(window);
  225.     if (!success) {
  226.       var err = this._manager.migrator.lastError;
  227.       if (err.severity < ffIErrorItem.SEVERITY_ERROR)
  228.         return;
  229.       prompter.alert(err.name, err.message);
  230.     } else
  231.       prompter.alert(this._bundle.getString("ff.import.title"), 
  232.                      this._bundle.getString("ff.import.success"));
  233.   },
  234.   
  235.   exportDOM: function Forecastfox_exportDOM()
  236.   {
  237.     var success = this._manager.migrator.exportDOM(window);
  238.     var prompter = this._getPrompter(window);
  239.     if (!success) {
  240.       var err = this._manager.migrator.lastError;
  241.       if (err.severity < ffIErrorItem.SEVERITY_ERROR)
  242.         return;
  243.       prompter.alert(err.name, err.message);
  244.     } else
  245.       prompter.alert(this._bundle.getString("ff.export.title"), 
  246.                      this._bundle.getString("ff.export.success"));
  247.   },
  248.   
  249.   _setOrient: function Forecastfox__setOrient(aOrient)
  250.   {
  251.     //element that need set
  252.     var ids = ["ff-box", "ff-weather", "ff-data-box", "ff-current-box", "ff-spacer",
  253.       "ff-forecast-box", "ff-today-panel", "ff-forecast-panel"];
  254.       
  255.     //set attribute
  256.     for (var x=0; x<ids.length; x++)
  257.       document.getElementById(ids[x]).setAttribute("orient", aOrient);
  258.   },
  259.     
  260.   _getWhere: function Forecastfox__getWhere(aEvent, aFrom)
  261.   {
  262.     //get left click default where
  263.     var where = this._manager.getPref("links." + aFrom);
  264.     
  265.     //get link modifier
  266.     try {
  267.       var pbs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
  268.       var appBranch = pbs.getBranch(null);
  269.       var background = appBranch.getBoolPref("browser.tabs.loadInBackground");
  270.     } catch(e) {
  271.       background = false;
  272.     }
  273.     
  274.     //determine if middle click 
  275.     var middle = (aEvent.button == 1);
  276.     
  277.     //get keys pressed
  278.     var ctrl = aEvent.ctrlKey;
  279.     var shift = aEvent.shiftKey;
  280.     
  281.     //do key based modifiers
  282.     if (ctrl || middle) {
  283.       if (shift || background)
  284.         where = "tabshifted";
  285.       else
  286.         where = "tab";
  287.     } else if (shift)
  288.       where = "window";
  289.           
  290.     return where;
  291.   },
  292.    
  293.   _moveBox: function Forecastfox__moveBox()
  294.   {
  295.     //check if box is in the right location
  296.     var toolbar = document.getElementById(this._manager.getPref("general.bar"));
  297.     var box = document.getElementById("ff-box");
  298.     var position = this._manager.getPref("general.position");
  299.     
  300.     //if toolbar doesn't exist move to default location
  301.     if (!toolbar) {
  302.       this._manager.setPref("general.bar", "status-bar");
  303.       this._manager.setPref("general.position", -1);
  304.       return;
  305.     }
  306.  
  307.     // set the orientation
  308.     var orient = document.defaultView.getComputedStyle(toolbar, "").getPropertyValue("-moz-box-orient");
  309.     this._setOrient(orient);   
  310.         
  311.     // bail if it is in the right place
  312.     if (this._indexOf(toolbar,box) == position)
  313.       return;
  314.  
  315.     //remove us from parent
  316.     box.parentNode.removeChild(box);
  317.     
  318.     //make sure we have the right element type
  319.     var newbox = null;
  320.     if (toolbar.localName == "statusbar") {
  321.       if (box.localName != "statusbarpanel")
  322.         newbox = document.createElement("statusbarpanel");
  323.     } else {
  324.       if (box.localName == "statusbarpanel")
  325.         newbox = document.createElement("hbox");    
  326.     }
  327.     
  328.     //append children of old box
  329.     if (newbox) {
  330.       newbox.setAttribute("id", "ff-box");
  331.       while (box.hasChildNodes())
  332.         newbox.appendChild(box.firstChild);      
  333.     } else
  334.       newbox = box;
  335.     
  336.     //insert us in correct place
  337.     this._insertAtIndex(toolbar, newbox, position);
  338.   },
  339.   
  340.   _indexOf: function Forecastfox__indexOf(aParent, aChild)
  341.   {
  342.     // -1 if it does not exist
  343.     var children = aParent.childNodes;
  344.     for (var x=0; x<children.length; x++) {
  345.       if (children[x] == aChild)
  346.         return (x == children.length - 1) ? -1 : x;
  347.     }
  348.     return null;
  349.   },
  350.   
  351.   _insertAtIndex: function Forecastfox__insertAtIndex(aParent, aChild, aIndex)
  352.   {
  353.     var children = aParent.childNodes;
  354.     if ((children.length == 0) || (aIndex >= children.length) || (aIndex < 0))
  355.       aParent.appendChild(aChild);
  356.     else
  357.       aParent.insertBefore(aChild, children[aIndex]);
  358.   },
  359.   
  360.   _update: function Forecastfox__update(aMethod)
  361.   {
  362.     var err;
  363.     
  364.     //update all
  365.     if (aMethod == "display") {
  366.       this._update("startUpdate");
  367.       this._update("endUpdate");
  368.     }
  369.     
  370.     //check for an error
  371.     if (aMethod == "endUpdate") {
  372.       err = this._manager.lastError;
  373.       if (err.severity != ffIErrorItem.SEVERITY_INFO) {
  374.         this._update("startUpdate");
  375.         this._update("lastError");
  376.         return;
  377.       }
  378.     }
  379.     
  380.     //move box
  381.     this._moveBox();
  382.         
  383.     //remove progress and errors
  384.     this._removeIndicator();
  385.     
  386.     //now do update
  387.     switch (aMethod) {
  388.       case "startUpdate":
  389.         this._showIndicator("progress");
  390.         break;
  391.       case "lastError":
  392.         this._showIndicator("error");
  393.         break;
  394.       case "endUpdate":
  395.       default:
  396.         this._showData();
  397.         this._showCurrent();
  398.         this._showForecast();
  399.         break;
  400.     }
  401.      
  402.     // set the borders
  403.     this._borders();
  404.   },
  405.  
  406.   _removeIndicator: function Forecastfox__removeIndicator()
  407.   {
  408.     var item = document.getElementById("ff-indicator"); 
  409.     
  410.     // clear the progress timer
  411.     if (this._timer) {
  412.       window.clearTimeout(this._timer);
  413.       this._timer = null;
  414.     }
  415.     
  416.     //remove the indicator  
  417.     item.removeAttribute("tooltiptext");
  418.     item.removeAttribute("label");
  419.     item.removeAttribute("src");
  420.     item.removeAttribute("type");
  421.     item.setAttribute("collapsed", true);
  422.   },
  423.  
  424.   _showIndicator: function Forecastfox__showIndicator(type)
  425.   {
  426.     var item = document.getElementById("ff-indicator");   
  427.     item.setAttribute("type", type);
  428.     
  429.     switch (type) {
  430.             
  431.     //set error    
  432.     case "error":
  433.       var err = this._manager.lastError;
  434.       item.setAttribute("label", err.name);
  435.       item.setAttribute("tooltiptext", err.message);
  436.       item.setAttribute("src", "chrome://global/skin/icons/error-16.png");  
  437.       break;
  438.     
  439.     // set the progress
  440.     case "progress":
  441.       item.removeAttribute("label");
  442.       item.setAttribute("tooltiptext", this._bundle.getString("ff.tooltip.loading"));
  443.       item.setAttribute("src", "chrome://global/skin/icons/loading_16.png");
  444.       var self = this;
  445.       this._timer = window.setTimeout(function() { self._showIndicator("timer"); }, FF_TIMER);     
  446.       break;
  447.         
  448.     // set the timer message
  449.     case "timer":
  450.       this._timer = null;
  451.       item.setAttribute("label", this._bundle.getString("ff.manager.timeout.name"));  
  452.       item.setAttribute("tooltiptext", this._bundle.getString("ff.manager.timeout.name"));  
  453.       item.setAttribute("src", "chrome://global/skin/icons/warning-16.png");
  454.       break;
  455.       
  456.     default:
  457.       return;
  458.     }
  459.     
  460.     //show panel
  461.     item.removeAttribute("collapsed");
  462.   },
  463.  
  464.   _showData: function Forecastfox_showData() {  
  465.     var swa = this._getItem("swa", "panel");
  466.     var logo = this._getItem("logo", "panel");
  467.     var hbh = this._getItem("hbh", "panel");
  468.     var hbh_menu = this._getItem("popup", "hbh");
  469.     var fiveday = this._getItem("fiveday", "panel");
  470.     var fiveday_menu = this._getItem("popup", "fiveday");
  471.     
  472.     //remove tooltip and attributes
  473.     this._evictImages(swa);
  474.     this._evictImages(logo);    
  475.     this._evictImages(hbh);
  476.     this._evictImages(fiveday);
  477.     swa.removeAttribute("src");
  478.     swa.removeAttribute("label");
  479.     logo.removeAttribute("src");
  480.     logo.removeAttribute("label");    
  481.     hbh.removeAttribute("src");
  482.     hbh.removeAttribute("label");
  483.     fiveday.removeAttribute("src");
  484.     fiveday.removeAttribute("label");
  485.     
  486.     //do swa
  487.     if (!this._manager.getPref("swa.panel.enabled") || this._manager.parser.getValue("swa", 0, "active", null) != "true")    
  488.       swa.setAttribute("collapsed", "true");
  489.     else {
  490.       this._setPanel(swa, "swa", "swa", null);      
  491.       swa.setAttribute("url", this._manager.parser.getValue("swa", 0, "url", null));
  492.       swa.removeAttribute("collapsed");       
  493.     } 
  494.     
  495.     // set logo
  496.     logo.setAttribute("collapsed", "true");
  497.     var url = this._manager.parser.getValue("logo", 0, "url", null);
  498.     if (false && url && url != "N/A") {
  499.       logo.setAttribute("url", url);
  500.       logo.setAttribute("src", this._manager.parser.getValue("logo", 0, "imagepath", null));
  501.       logo.setAttribute("tooltipenabled", "true");
  502.       logo.setAttribute("tooltipdisplay", "0");
  503.       logo.setAttribute("tooltipsrc", this._manager.parser.getValue("logo", 0, "tooltippath", null));
  504.       logo.setAttribute("tooltipwidth", this._manager.parser.getValue("logo", 0, "tooltipwidth", null));    
  505.       logo.setAttribute("tooltipheight", this._manager.parser.getValue("logo", 0, "tooltipheight", null));      
  506.       logo.setAttribute("prefix", "logo");
  507.       logo.setAttribute("tooltiplabel", "");
  508.       logo.setAttribute("tooltiptitle", "");
  509.       logo.setAttribute("tooltip", "ff-tooltip"); 
  510.       logo.removeAttribute("collapsed");
  511.       FFTracker.trackURL(this._manager.parser.getValue("logo", 0, "track", null));
  512.     }
  513.     
  514.     // set hbh
  515.     hbh.setAttribute("collapsed", "true");
  516.     hbh_menu.setAttribute("hidden", "true");
  517.     url = this._manager.parser.getValue("days", 0, "hbh", null);    
  518.     if (url && url != "N/A") {
  519.         hbh_menu.setAttribute("url", url);
  520.         hbh_menu.removeAttribute("hidden");        
  521.     }
  522.     if (this._manager.getPref("hbh.panel.enabled") && url && url != "N/A") {
  523.       hbh.setAttribute("url", url);        
  524.       hbh.setAttribute("src", "chrome://forecastfox/skin/images/hbh.png");
  525.       hbh.setAttribute("tooltipenabled", "true");
  526.       hbh.setAttribute("tooltipdisplay", "1");
  527.       hbh.setAttribute("tooltipsrc", "");
  528.       hbh.setAttribute("prefix", "hbh");
  529.       hbh.setAttribute("tooltiplabel", this._bundle.getString("ff.hbh.title"));
  530.       hbh.setAttribute("tooltiptitle", "");
  531.       hbh.setAttribute("tooltip", "ff-tooltip"); 
  532.       hbh.removeAttribute("collapsed");
  533.     }
  534.     
  535.     // set fiveday
  536.     fiveday.setAttribute("collapsed", "true");
  537.     fiveday_menu.setAttribute("hidden", "true"); 
  538.     url = this._manager.parser.getValue("days", 0, "url5day", null);  
  539.     if (url && url != "N/A") {
  540.         fiveday_menu.setAttribute("url", url);
  541.         fiveday_menu.removeAttribute("hidden");        
  542.     }    
  543.     if (this._manager.getPref("fiveday.panel.enabled") && url && url != "N/A") {
  544.       fiveday_menu.setAttribute("url", url);
  545.       fiveday.setAttribute("url", url);
  546.       fiveday.setAttribute("src", "chrome://forecastfox/skin/images/5day.png");
  547.       fiveday.setAttribute("tooltipenabled", "true");
  548.       fiveday.setAttribute("tooltipdisplay", "1");
  549.       fiveday.setAttribute("tooltipsrc", "");
  550.       fiveday.setAttribute("prefix", "fiveday");
  551.       fiveday.setAttribute("tooltiplabel", this._bundle.getString("ff.fiveday.title"));
  552.       fiveday.setAttribute("tooltiptitle", "");
  553.       fiveday.setAttribute("tooltip", "ff-tooltip"); 
  554.       fiveday.removeAttribute("collapsed");
  555.     }    
  556.   },
  557.   
  558.   _showCurrent: function Forecastfox__showCurrent()
  559.   {
  560.     var current = this._getItem("current", "panel");
  561.     var radar = this._getItem("radar", "panel");
  562.        
  563.     //remove tooltip and attributes
  564.     this._evictImages(current);
  565.     this._evictImages(radar);
  566.     current.removeAttribute("src");
  567.     current.removeAttribute("label");
  568.     radar.removeAttribute("src");
  569.     radar.removeAttribute("label");
  570.         
  571.     //do current
  572.     if (!this._manager.getPref("cc.panel.enabled"))
  573.       current.setAttribute("collapsed", "true");
  574.     else {
  575.       this._setPanel(current, "cc", null, null);
  576.       current.setAttribute("url", this._manager.parser.getValue("current", 0, "url", null));
  577.       current.removeAttribute("collapsed"); 
  578.     }
  579.     
  580.     //do radar
  581.     if (!this._manager.getPref("radar.panel.enabled"))    
  582.       radar.setAttribute("collapsed", "true");
  583.     else {
  584.       this._setPanel(radar, "radar", "radar", null);
  585.       
  586.       radar.setAttribute("url", this._manager.parser.getValue("radar", 0, "url", null));
  587.       
  588.       // only display the radar node if there is radar
  589.       var image = this._manager.parser.getValue("radar", 0, "image", null);
  590.       if (image && image != "N/A")
  591.         radar.removeAttribute("collapsed");
  592.       else
  593.         radar.setAttribute("collapsed", true);
  594.     }     
  595.   },
  596.   
  597.   _showForecast: function Forecastfox__showForecast()
  598.   {
  599.     var today = this._getItem("today", "panel");
  600.     var extended = this._getItem("forecast", "panel");
  601.        
  602.     //remove tooltip and attributes
  603.     while (today.hasChildNodes()) {
  604.       this._evictImages(today.lastChild);
  605.       today.lastChild.removeAttribute("src");
  606.       today.lastChild.removeAttribute("label");
  607.       today.removeChild(today.lastChild);
  608.     }
  609.     while (extended.hasChildNodes()) {
  610.       this._evictImages(extended.lastChild);    
  611.       extended.lastChild.removeAttribute("src");
  612.       extended.lastChild.removeAttribute("label");
  613.       extended.removeChild(extended.lastChild);
  614.     }      
  615.     
  616.     //set url for popup menu since it is the same for all forecast days
  617.     var menu = document.getElementById("ff-popup-forecast");
  618.     menu.setAttribute("url", this._manager.parser.getValue("days", 0, "url", null));
  619.     
  620.     //do today
  621.     if (!this._manager.getPref("dayt.panel.enabled") || (this._manager.getPref("dayt.panel.mode") < 0))
  622.       today.setAttribute("collapsed", "true");
  623.     else
  624.       this._updateToday(today);
  625.   
  626.     //do extended
  627.     if (!this._manager.getPref("dayf.panel.enabled") || (this._manager.getPref("dayf.panel.days") == 0)) 
  628.       extended.setAttribute("collapsed", "true");
  629.     else
  630.       this._updateExtended(extended);
  631.   },
  632.   
  633.   _updateToday: function Forecastfox__updateToday(aNode)
  634.   {    
  635.     var mode = this._manager.getPref("dayt.panel.mode");
  636.     var sw_mode = this._manager.getPref("dayt.panel.switch");
  637.     var panels = (mode == 2) ? 2 : 1;
  638.     var cHours = this._getHour();
  639.     var day_index = 0;
  640.       
  641.     while (this._shouldIncDay(day_index, cHours))
  642.       day_index++;
  643.       
  644.     for (var x = 0; x < panels; x++) {
  645.       
  646.       if (cHours <= FF_TIME_NIGHT || cHours >= FF_TIME_DAY) {
  647.         if (mode == 0 && sw_mode == 1)
  648.           day_index++;
  649.         else if (mode == 2)
  650.           panels--;
  651.       }
  652.  
  653.       if (this._shouldCreatePanel("today", "days", x, cHours))
  654.         this._createPanel("today", aNode, "days", day_index);
  655.       else if (this._shouldCreatePanel("today", "nights", x, cHours))
  656.         this._createPanel("today", aNode, "nights", day_index);
  657.     }
  658.       
  659.     // show the box!
  660.     aNode.removeAttribute("collapsed");
  661.   },
  662.   
  663.   _updateExtended: function Forecastfox__updateExtended(aNode)
  664.   {
  665.       var days = this._manager.getPref("dayf.panel.days");
  666.     var new_panel = false;
  667.     var cHours    = this._getHour();
  668.     var day_index = 1;
  669.     var day_add   = 0;
  670.  
  671.     while (this._shouldIncDay(day_add, cHours))
  672.       day_add++;
  673.       
  674.     day_index += day_add;
  675.         
  676.     for (var x = 0; x < days; day_index++) {
  677.       // finish if we went through too many days
  678.       if (day_index > 8)
  679.         break;
  680.         
  681.       try {
  682.         // create the corresponding nodes
  683.         if (this._shouldCreatePanel("extended", "days", day_index, cHours))
  684.           new_panel = this._createPanel("extended", aNode, "days", day_index);
  685.       } catch (e) {}
  686.       
  687.       try {
  688.         if (this._shouldCreatePanel("extended", "nights", day_index, cHours))
  689.           new_panel = this._createPanel("extended", aNode, "nights", day_index);
  690.       } catch (e) {}
  691.       
  692.       // increase x if we made a new one
  693.       if (new_panel)
  694.         x++;
  695.       
  696.       new_panel = false;
  697.     }
  698.     
  699.     aNode.removeAttribute("collapsed");
  700.   },
  701.   
  702.   _shouldIncDay: function Forecastfox__shouldIncDay(aIndex, aHours)
  703.   {    
  704.     return ((aHours < 12 && !this._hasData(aIndex)) && 
  705.             (FF_TIME_NIGHT < aHours && aHours < FF_TIME_DAY));
  706.   },
  707.   
  708.   _hasData: function Forecastfox__hasData(aIndex)
  709.   {
  710.     return ((this._manager.parser.getValue("days", aIndex, "t", null) != "N/A") ||
  711.             (this._manager.parser.getValue("days", aIndex, "tlong", null) != "N/A"));
  712.   },
  713.   
  714.   _shouldCreatePanel: function Forecastfox__shouldCreatePanel(aType, aPart, aIndex, aHours)      
  715.   {
  716.     var mode, sw_mode, cHours, t_mode, t_sw_mode, t_on;    
  717.     switch (aType) {
  718.       case "today":
  719.         mode = this._manager.getPref("dayt.panel.mode");
  720.           sw_mode = this._manager.getPref("dayt.panel.switch");
  721.         
  722.         switch (aPart) {
  723.           case "days":
  724.             if (aHours > FF_TIME_NIGHT && aHours < FF_TIME_DAY)
  725.               return ((mode == 0) || (mode == 2 && aIndex == 0));
  726.             else
  727.               return ((mode == 0 && sw_mode == 1) || (mode == 2 && aIndex == 2));
  728.           case "nights":
  729.             if (mode == 1)
  730.               return true;
  731.             else if (aHours > FF_TIME_NIGHT && aHours < FF_TIME_DAY)
  732.               return (mode == 2 && aIndex == 1);
  733.             else
  734.               return ((mode == 0 && sw_mode == 0) || (mode == 2));
  735.         }
  736.         break;
  737.       case "extended":
  738.         mode = this._manager.getPref("dayf.panel.mode");
  739.         t_mode = this._manager.getPref("dayt.panel.mode");
  740.         t_sw_mode = this._manager.getPref("dayt.panel.switch");
  741.         t_on = this._manager.getPref("dayt.panel.enabled");
  742.  
  743.         switch (aPart) {
  744.           
  745.           case "nights":
  746.             return ((mode == 1) || (mode == 2));
  747.           case "days":
  748.             // if we're displaying days or days and nights
  749.             if (mode == 0 || mode == 2) {
  750.               // If its between the "days" hours
  751.               if (FF_TIME_NIGHT < aHours && aHours < FF_TIME_DAY)
  752.                 return true;
  753.               // If its between the "nights" hours
  754.               else
  755.                 return ((t_mode != 0) || (!t_on || (aIndex != 1 && t_sw_mode == 1)) || (t_sw_mode != 1));
  756.             }
  757.             else
  758.               return false;
  759.         }
  760.         break;
  761.     }
  762.     
  763.     return false;
  764.   },
  765.   
  766.   _createPanel: function Forecastfox__createPanel(aGroup, aParent, aPart, aDay)
  767.   {
  768.     var node = document.createElement("ffpanel");
  769.     var prefix = (aGroup == "extended") ? "dayf" : "dayt";
  770.     
  771.     //set context menu on node
  772.     node.setAttribute("context","ff-popup");
  773.     node.setAttribute("id", "forecast" + aPart + aDay);
  774.     node.setAttribute("url", this._manager.parser.getValue(aPart, aDay, "url", null));
  775.     node.setAttribute("tooltip", "ff-tooltip");
  776.     node.setAttribute("tooltipad", "false");
  777.     
  778.     //set panel and append
  779.     this._setPanel(node, prefix, aPart, aDay);
  780.     aParent.appendChild(node);
  781.     
  782.     // return that one was made
  783.     return true;
  784.   },
  785.       
  786.   _getItem: function Forecastfox__getItem(aItem, aType)
  787.   {
  788.     var item = null;
  789.     item = document.getElementById("ff-" + aItem + "-" + aType);
  790.     return item;  
  791.   },
  792.   
  793.   _getHour: function Forecastfox__getHour()
  794.   {
  795.     var time = this._manager.parser.getValue("global", 0, "tm", null);
  796.     var ind = time.indexOf(":");
  797.     if (ind < 0) {
  798.       time = Number(this._manager.getPref("general.last"));
  799.       return (new Date(time)).getHours();
  800.     }
  801.     return Number(time.substring(0,ind));
  802.   },
  803.   
  804.   _setPanel: function Forecastfox__setPanel(aNode, aPrefix, aGroup, aIndex)
  805.   {
  806.     //if group isn't provided get from prefix
  807.     if (!aGroup)
  808.       aGroup = this._prefixes[aPrefix];
  809.       
  810.     //set tooltip
  811.     this._setTooltip(aNode, aPrefix, aGroup, aIndex);
  812.        
  813.     //set display  
  814.     var icon = this._manager.parser.getValue(aGroup, aIndex, "icon", null);
  815.     var label = this._manager.parser.getLabel(this._manager.getPref(aPrefix + ".panel.label"), aGroup, aIndex);
  816.     icon = this._manager.icons.current.getItem(icon + "-small");
  817.     var width = icon.width;
  818.     var height = icon.height;
  819.     switch (this._manager.getPref(aPrefix + ".panel.display")) {
  820.       case 1:
  821.         aNode.setAttribute("label", label);
  822.         aNode.setAttribute("crop", "right");
  823.         break;
  824.       case 2:
  825.         aNode.setAttribute("src", icon.URL);
  826.         if (width)
  827.           aNode.setAttribute("imagewidth", width);
  828.         if (height)
  829.           aNode.setAttribute("imageheight", height);
  830.         aNode.setAttribute("label", label); 
  831.         aNode.setAttribute("crop", "right");       
  832.         break;
  833.       case 0:
  834.       default:
  835.         aNode.setAttribute("src", icon.URL);
  836.         if (width)
  837.           aNode.setAttribute("imagewidth", width);
  838.         if (height)
  839.           aNode.setAttribute("imageheight", height);
  840.         break;
  841.     }
  842.   },
  843.  
  844.   _setTooltip: function Forecastfox__setTooltip(aNode, aPrefix, aGroup, aIndex)
  845.   {
  846.     //if group isn't provided get from prefix
  847.     if (!aGroup)
  848.       aGroup = this._prefixes[aPrefix];
  849.     
  850.     //get the tooltip enabled and display prefs
  851.     var enabled = this._manager.getPref(aPrefix + ".tooltip.enabled");
  852.     var display = this._manager.getPref(aPrefix + ".tooltip.display");
  853.               
  854.     //get icon attributes
  855.     var icon = this._manager.parser.getValue(aGroup, aIndex, "icon", null);
  856.     icon = this._manager.icons.current.getItem(icon + "-large");
  857.     var src = icon.URL;
  858.     var width = icon.width;
  859.     var height = icon.height;
  860.     
  861.     //get the label attributes
  862.     var label = this._manager.getPref(aPrefix + ".tooltip.label");    
  863.     label = this._manager.parser.getLabel(label, aGroup, aIndex);
  864.     var title = this._manager.getPref(aPrefix + ".tooltip.title"); 
  865.     title = this._manager.parser.getLabel(title, aGroup, aIndex);    
  866.  
  867.     //set the attributes on the node
  868.     aNode.setAttribute("tooltipenabled", String(enabled));
  869.     aNode.setAttribute("tooltipdisplay", String(display));
  870.     aNode.setAttribute("tooltipsrc", String(src));
  871.     aNode.setAttribute("prefix", aPrefix);
  872.     if (width)
  873.       aNode.setAttribute("tooltipwidth", String(width));
  874.     if (height)
  875.       aNode.setAttribute("tooltipheight", String(height));
  876.     aNode.setAttribute("tooltiptitle", title);
  877.     aNode.setAttribute("tooltiplabel", label);
  878.     aNode.setAttribute("tooltip", "ff-tooltip");    
  879.   },
  880.   
  881.   _borders: function Forecastfox__borders()
  882.   {
  883.     //get elements
  884.     var spacer = document.getElementById("ff-spacer");
  885.     var today = this._getItem("today", "panel");
  886.     var extended = this._getItem("forecast", "panel");
  887.     var radar = this._getItem("radar", "panel");
  888.     var swa = this._getItem("swa", "panel");
  889.     var current = this._getItem("current", "panel");
  890.     
  891.     var showing = new Object();
  892.     
  893.     //determine what is showing
  894.     showing["current"] = (this._manager.getPref("cc.panel.enabled") && !current.hasAttribute("collapsed"));
  895.     showing["radar"] = (this._manager.getPref("radar.panel.enabled") && !radar.hasAttribute("collapsed"));
  896.     showing["swa"] = (this._manager.getPref("swa.panel.enabled") && !swa.hasAttribute("collapsed"));
  897.     showing["today"] = (this._manager.getPref("dayt.panel.enabled") && today.hasChildNodes() && !today.hasAttribute("collapsed"));
  898.     showing["extended"] = (this._manager.getPref("dayf.panel.enabled") && extended.hasChildNodes() && !extended.hasAttribute("collapsed"));
  899.     
  900.     //show-hide spacer
  901.     var cShowing = (showing["current"] || showing["radar"] || showing["swa"]);
  902.     var fShowing = (showing["today"] || showing["extended"]);
  903.     if (cShowing && fShowing)
  904.       spacer.removeAttribute("collapsed");
  905.     else
  906.       spacer.setAttribute("collapsed", "true");
  907.         
  908.     //remove old first-last attribute
  909.     var box = document.getElementById("ff-box");
  910.     var panels = box.getElementsByTagName("ffpanel");
  911.     for (var x=0; x<panels.length; x++) {
  912.       panels[x].removeAttribute("ff-first");
  913.       panels[x].removeAttribute("ff-last");
  914.     }
  915.     
  916.     //set first attribute
  917.     if (showing["swa"])
  918.       swa.setAttribute("ff-first", "true");    
  919.     else if (showing["radar"])
  920.       radar.setAttribute("ff-first", "true");
  921.     else if (showing["current"])
  922.       current.setAttribute("ff-first", "true");
  923.     else if (showing["today"])
  924.       today.firstChild.setAttribute("ff-first", "true");
  925.     else if (showing["extended"])
  926.       extended.firstChild.setAttribute("ff-first", "true");
  927.  
  928.     //set last attribute
  929.     if (showing["extended"])
  930.       extended.lastChild.setAttribute("ff-last", "true");
  931.     else if (showing["today"])
  932.       today.lastChild.setAttribute("ff-last", "true");
  933.     else if (showing["current"])
  934.       current.setAttribute("ff-last", "true");
  935.     else if (showing["radar"])
  936.       radar.setAttribute("ff-last", "true");
  937.     else if (showing["swa"])
  938.       swa.setAttribute("ff-last", "true");
  939.   },
  940.   
  941.   _evictImages: function Forecastfox__evictImages(aNode)
  942.   {
  943.     //remove the source image
  944.     var image = aNode.getAttribute("src");
  945.     if (image != "")
  946.       this._manager.evictImage(image);
  947.       
  948.     //remove the tooltip source image
  949.     image = aNode.getAttribute("tooltipsrc");
  950.     if (image != "")
  951.       this._manager.evictImage(image);
  952.   },
  953.   
  954.   _getPrompter: function Forecastfox__getPrompter(aParent)
  955.   {
  956.     //get the watcher service
  957.     var watcher = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
  958.                   getService(Components.interfaces.nsIWindowWatcher);
  959.                 
  960.     //return a prompter
  961.     return watcher.getNewPrompter(aParent);
  962.   },
  963.   
  964.   openDialog: function Forecastfox_openDialog(aType)
  965.   {
  966.     //focus the window if already open
  967.     var mediator = Components.classes['@mozilla.org/appshell/window-mediator;1'].
  968.                    getService(Components.interfaces.nsIWindowMediator);
  969.     var win = mediator.getMostRecentWindow(aType);
  970.     if (win) {
  971.       win.focus();
  972.       return;
  973.     }
  974.       
  975.     //open a new window       
  976.     switch (aType) {
  977.     case "forecastfox:options":
  978.       window.openDialog("chrome://forecastfox/content/options/options.xul", "options", "chrome");
  979.       break;
  980.       
  981.     case "forecastfox:about":
  982.       window.openDialog("chrome://forecastfox/content/about.xul", "ff-about", "chrome");
  983.       break;
  984.     default:
  985.       break;
  986.     }
  987.   }
  988. };